/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.icee.myth.server.sandbox;

import com.icee.myth.log.GameLogger;
import com.icee.myth.log.message.FileDebugGameLogMessage;
import com.icee.myth.log.message.builder.GameLogMessageBuilder;
import com.icee.myth.server.actor.Human;
import com.icee.myth.protobuf.ExternalCommonProtocol.SandboxProto;
import com.icee.myth.protobuf.ExternalCommonProtocol.VariableValueProto;
import com.icee.myth.protobuf.builder.ClientToMapBuilder;
import com.icee.myth.server.GameServer;
import com.icee.myth.server.base.occupy.OccupyInfo;
import com.icee.myth.server.base.occupy.OccupyInfos;
import com.icee.myth.server.card.Card;
import com.icee.myth.server.levelup.HumanLevelsConfig;
import com.icee.myth.server.slot.LocationSensitiveCardSlots;
import com.icee.myth.utils.Consts;
import java.util.List;

/**
 *
 * @author liuxianke
 */
public class SandBox extends LocationSensitiveCardSlots {
    public int leader;  // 队长卡片槽位号
    public int helper;  // 友军卡片槽位号
    
    public SandBox(Human human, SandboxProto sandBoxProto) {
        super(human, Consts.PLACE_TYPE_SANDBOX, Consts.MAX_SANDBOX_SLOT_NUM, (sandBoxProto != null)?sandBoxProto.getSlots():null);

        if (sandBoxProto != null) {
            leader = sandBoxProto.getLeader();
            helper = sandBoxProto.getHelper();
        }
    }

    public SandboxProto buildSandboxProto() {
        SandboxProto.Builder builder1 = SandboxProto.newBuilder();

        builder1.setLeader(leader);
        builder1.setHelper(helper);
        builder1.setSlots(buildSlotsProto());

        return builder1.build();
    }

    private NewSandBoxSlotsInfo getNewSandboxSlots(SandboxProto sandBoxProto) {
        NewSandBoxSlotsInfo newSandBoxSlotsInfo = new NewSandBoxSlotsInfo();
        List<VariableValueProto> variableValueProtos = sandBoxProto.getSlots().getValuesList();
        for (VariableValueProto variableValueProto : variableValueProtos) {
            int slotId = variableValueProto.getId();
            if ((slotId >= 0) && (slotId < Consts.MAX_SANDBOX_SLOT_NUM)) {
                if (newSandBoxSlotsInfo.slots[variableValueProto.getId()] == null) {
                    int cardInstId = (int)variableValueProto.getValue();
                    Card card = human.cards.getCard(cardInstId);
                    if (card != null) {
                        // 卡片不能配置在其他地方
                        if ((card.place == Consts.PLACE_TYPE_SANDBOX) || (card.place == Consts.PLACE_TYPE_NONE)) {
                            // 重复判断
                            boolean hasSame = false;
                            for (Card c : newSandBoxSlotsInfo.slots) {
                                if (c == card) {
                                    hasSame = true;
                                    break;
                                }
                            }

                            if (!hasSame) {
                                newSandBoxSlotsInfo.slots[slotId] = card;
                                newSandBoxSlotsInfo.leaderPoint += card.staticInfo.leadPoint;
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Player[" + human.id + "] change sandbox error because card[" + cardInstId + "] in more than one slot."));
                                return null;
                            }
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Player[" + human.id + "] change sandbox error because card[" + cardInstId + "] in place[" + card.place + "]."));
                            return null;
                        }
                    } else {
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                "Player[" + human.id + "] change sandbox error because card[" + cardInstId + "] not exist."));
                        return null;
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + human.id + "] change sandbox error because cards in same slot."));
                    return null;
                }
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] change sandbox error because slot[" + slotId + "] out of range."));
                return null;
            }
        }

        return newSandBoxSlotsInfo;
    }

    private boolean change(Card[] newSlots, int newLeader, int newHelper) {
        if (newSlots != null) {
            if (newSlots[newHelper] == null) {
                if (newSlots[newLeader] != null) {
                    // 校验阵型改变
                    if ((newLeader != leader) || (newHelper != helper) || !sameSlots(newSlots, slots)) {
                        if (slots[leader] != newSlots[newLeader]) {
                            // 改变全局玩家简略信息中的队长卡片信息
                            Card newLeaderCard = newSlots[newLeader];
                            GameServer.INSTANCE.briefPlayerInfos.setPlayerLeaderCard(human.id, newLeaderCard.staticInfo.id, newLeaderCard.level);

                            // 改变臣属信息中的队长卡片信息
                            OccupyInfo occupyInfo = OccupyInfos.INSTANCE.getOccupyInfo(human.id);
                            if ((occupyInfo != null) && occupyInfo.inited) {
                                occupyInfo.leaderCardId = newLeaderCard.staticInfo.id;
                                occupyInfo.leaderCardLevel = newLeaderCard.level;
                            }

                            // 通知朋友队长信息改变
                            human.broadcastToFriends(ClientToMapBuilder.buildFriendLeaderCardChange(human.id, newLeaderCard.staticInfo.id, newLeaderCard.level));
                        }

                        change(newSlots);

                        leader = newLeader;
                        helper = newHelper;

                        human.sendMessage(ClientToMapBuilder.buildSandBoxInfo(buildSandboxProto()));

                        // 判断最大战斗力是否改变
                        human.checkMaxPowerChange();

                        return true;
                    } else {
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                "Player[" + human.id + "] change sandbox error because nothing to change."));
                        return false;
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + human.id + "] change sandbox error because wrong leader."));
                }
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] change sandbox error because wrong friend slot."));
            }
        }
        return false;
    }

    public boolean littleChange(SandboxProto sandBoxProto) {
        NewSandBoxSlotsInfo newSandBoxSlotsInfo = getNewSandboxSlots(sandBoxProto);
        if (newSandBoxSlotsInfo != null) {
            int newLeader = sandBoxProto.getLeader();
            int newHelper = sandBoxProto.getHelper();

            // 校验新阵型中卡片是否在旧阵型中出现
            for (int i=0; i<Consts.MAX_SANDBOX_SLOT_NUM; i++) {
                if ((newSandBoxSlotsInfo.slots[i] != null) && (newSandBoxSlotsInfo.slots[i].place != Consts.PLACE_TYPE_SANDBOX)) {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + human.id + "] change sandbox error because try to add card[" + newSandBoxSlotsInfo.slots[i] + "] to sandbox in stage."));

                    return false;
                }
            }

            // 校验主将是否更换
            if (newSandBoxSlotsInfo.slots[newLeader] == slots[leader]) {
                return change(newSandBoxSlotsInfo.slots, newLeader, newHelper);
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] change sandbox error because try to change leader in stage."));
            }
        }

        return false;
    }

    public boolean change(SandboxProto sandBoxProto) {
        NewSandBoxSlotsInfo newSandBoxSlotsInfo = getNewSandboxSlots(sandBoxProto);
        if (newSandBoxSlotsInfo != null) {
            int newLeader = sandBoxProto.getLeader();
            int newHelper = sandBoxProto.getHelper();

            // 校验领导力
            if (newSandBoxSlotsInfo.leaderPoint <= HumanLevelsConfig.INSTANCE.levelConfigs[human.lv - 1].leaderPoint) {
                return change(newSandBoxSlotsInfo.slots, newLeader, newHelper);
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] change sandbox error because not enough leader point."));
            }
        }
        
        return false;
    }

    public int getCurrentPower() {
        int currentPower = 0;

        float atkUp = human.getAtkUp();
        float hpUp = human.getHpUp();
        int hitAndDodUp = human.getHitAndDodUp();
        int criAndTenUp = human.getCriAndTenUp();
        for (int i=0; i<Consts.MAX_SANDBOX_SLOT_NUM; i++) {
            Card card = slots[i];
            if (card != null) {
                currentPower += card.getPower(atkUp, hpUp, hitAndDodUp, criAndTenUp);
            }
        }

        return currentPower;
    }

    public int getTotalLeaderPoint() {
        int totalLeaderPoint = 0;
        for (int i=0; i<Consts.MAX_SANDBOX_SLOT_NUM; i++) {
            Card card = slots[i];
            if (card != null) {
                totalLeaderPoint += card.staticInfo.leadPoint;
            }
        }
        return totalLeaderPoint;
    }
}
